home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 12 / Amiga Format AFCD12 (Apr 1997, Issue 96).iso / -in_the_mag- / emulation / fs1541 / disk.c < prev    next >
C/C++ Source or Header  |  1997-02-09  |  6KB  |  336 lines

  1. /*
  2.     FS1541
  3.  
  4.     disk.c
  5.  
  6.  
  7.     Basic disk interaction routines.
  8.  
  9. */
  10.  
  11. #include <string.h>
  12.  
  13. #include <exec/types.h>
  14. #include <exec/execbase.h>
  15. #include <exec/memory.h>
  16. #include <exec/ports.h>
  17. #include <dos/dos.h>
  18. #include <intuition/intuition.h>
  19. #include <devices/timer.h>
  20.  
  21. #include <proto/exec.h>
  22. #include <proto/intuition.h>
  23.  
  24. #include "disk.h"
  25. #include "volume.h"
  26.  
  27. LONG numsofterrors = 0;
  28. static struct MsgPort *diskport;
  29. struct IOExtTD *diskreq;
  30. BOOL autoscan = TRUE;
  31.  
  32. struct MsgPort *dpsender;
  33.  
  34. static UBYTE *diskimage;
  35. static int diskscanned;
  36. static BYTE sectab[683];
  37. static int curblk = 357; /* Preloading starts at 18,0 = BAM */
  38. static int devopen = 0;
  39. ULONG chgcount;
  40.  
  41. static BOOL ignoreall, abortall;
  42.  
  43. struct IntuitionBase *IntuitionBase;
  44.  
  45. int wprotected;
  46.  
  47. static void cacheblock(ULONG n, BOOL write);
  48.  
  49. /*-------------------------------------------------------------------------*/
  50.  
  51. LONG InitDiskSS(STRPTR device, ULONG unit, ULONG flags)
  52. {
  53.     LONG error = 0;
  54.  
  55.     if((diskimage = AllocVec(D64_SIZE, MEMF_PUBLIC)))
  56.     {
  57.         if((diskport = CreateMsgPort()))
  58.         {
  59.             if((diskreq = CreateIORequest(diskport, sizeof(struct IOExtTD))))
  60.             {
  61.                 if((devopen = (!OpenDevice(device,unit,(struct IORequest *)diskreq,flags))))
  62.                 {
  63.     
  64.                     return(0);
  65.     
  66.                 } else error = ERROR_DEVICE_NOT_MOUNTED;
  67.             } else error = ERROR_NO_FREE_STORE;
  68.         } else error = ERROR_NO_FREE_STORE;
  69.     } else error = ERROR_NO_FREE_STORE;
  70.  
  71.     QuitDiskSS();
  72.     return(error);
  73. }
  74.  
  75. void QuitDiskSS(void)
  76. {
  77.     if(devopen)
  78.         CloseDevice((struct IORequest*)diskreq);
  79.  
  80.     if(diskreq)
  81.         DeleteIORequest(diskreq);
  82.  
  83.     if(diskport)
  84.         DeleteMsgPort(diskport);
  85.  
  86.     if(diskimage)
  87.         FreeVec(diskimage);
  88. }
  89.  
  90. /*-------------------------------------------------------------------------*/
  91.  
  92. void ResetDisk(void)
  93. {
  94.     diskscanned = !autoscan;
  95.  
  96.     memset(sectab, SEC_NOT_LOADED, 683);
  97.  
  98.     curblk = 357;
  99.  
  100.     abortall = FALSE;
  101.     ignoreall = FALSE;
  102.  
  103.     diskreq->iotd_Req.io_Command = TD_CHANGENUM;
  104.     diskreq->iotd_Req.io_Flags = IOF_QUICK;
  105.     DoIO((struct IORequest*)diskreq);
  106.     chgcount = diskreq->iotd_Req.io_Actual;
  107.  
  108.     diskreq->iotd_Req.io_Command = ETD_CLEAR;
  109.     diskreq->iotd_Count = chgcount;
  110.     diskreq->iotd_Req.io_Flags = IOF_QUICK;
  111.     DoIO((struct IORequest*)diskreq);
  112.  
  113.     diskreq->iotd_Req.io_Command = TD_PROTSTATUS;
  114.     diskreq->iotd_Req.io_Flags = IOF_QUICK;
  115.     DoIO((struct IORequest*)diskreq);
  116.     wprotected = diskreq->iotd_Req.io_Actual;
  117. }
  118.  
  119. /* Asynchronous disk preloader */
  120. BOOL LoadDisk(void)
  121. {
  122.     if(!diskscanned && curvolumenode && autoscan)
  123.     {
  124.         int readblk;
  125.  
  126.         for(readblk=curblk;readblk<683;readblk++)
  127.             if(sectab[readblk] == SEC_NOT_LOADED)
  128.                 break;
  129.  
  130.         if(readblk == 683)
  131.         {
  132.             if(curblk == 0)
  133.             {
  134.                 /* Loading finished - switch off motor. */
  135.                 diskreq->iotd_Req.io_Command = TD_MOTOR;
  136.                 diskreq->iotd_Req.io_Flags = 0;
  137.                 diskreq->iotd_Req.io_Length = 0;
  138.                 DoIO((struct IORequest*)diskreq);
  139.                 diskscanned = TRUE;
  140.                 return(TRUE);
  141.             }
  142.             else
  143.                 curblk = 0;
  144.  
  145.             return(FALSE);
  146.         }
  147.  
  148.         curblk = readblk;
  149.         cacheblock(readblk, FALSE);
  150.  
  151.         return(FALSE);
  152.  
  153.     } else return(TRUE);
  154. }
  155.  
  156. void MotorOff(void)
  157. {
  158.     if(diskscanned && CheckIO((struct IORequest*)UDStimer))
  159.     {
  160.         diskreq->iotd_Req.io_Command = ETD_UPDATE;
  161.         diskreq->iotd_Req.io_Flags = 0;
  162.         DoIO((struct IORequest*)diskreq);
  163.  
  164.         diskreq->iotd_Req.io_Command = TD_MOTOR;
  165.         diskreq->iotd_Req.io_Flags = 0;
  166.         diskreq->iotd_Req.io_Length = 0;
  167.         DoIO((struct IORequest*)diskreq);
  168.     }
  169. }
  170.  
  171. /*-------------------------------------------------------------------------*/
  172.  
  173. static LONG ts2block(UBYTE t, UBYTE s)
  174. {
  175.     if(t<1)
  176.     {
  177.         return(-1);
  178.     }
  179.     else if(t<=17)
  180.     {
  181.         if(s>21)
  182.             return(-1);
  183.         else
  184.             return(21*(t-1) + s);
  185.     }
  186.     else if(t<=24)
  187.     {
  188.         if(s>19)
  189.             return(-1);
  190.         else
  191.             return(21*17 + 19*(t-18) + s);
  192.     }
  193.     else if(t<=30)
  194.     {
  195.         if(s>18)
  196.             return(-1);
  197.         else
  198.             return(21*17 + 19*7 + 18*(t-25) + s);
  199.     }
  200.     else if(t<=35)
  201.     {
  202.         if(s>17)
  203.             return(-1);
  204.         else
  205.             return(21*17 + 19*7 + 18*6 + 17*(t-31) + s);
  206.     }
  207.     else
  208.         return(-1);
  209. }
  210.  
  211. struct DataBlock *getblock_ts(UBYTE t, UBYTE s)
  212. {
  213.     LONG blk = ts2block(t, s);
  214.  
  215.     if(blk>=0)
  216.         return(getputblock(blk, FALSE));
  217.     else
  218.         return(NULL);
  219. }
  220.  
  221. struct DataBlock *putblock_ts(UBYTE t, UBYTE s, APTR data)
  222. {
  223.     LONG blk = ts2block(t, s);
  224.  
  225.     if(blk>=0)
  226.     {
  227.         CopyMem(data, diskimage+(blk*256), 256);
  228.         return(getputblock(blk, TRUE));
  229.     }
  230.     else
  231.         return(NULL);
  232. }
  233.  
  234. struct DataBlock *getputblock(ULONG blk, BOOL write)
  235. {
  236.     if(write)
  237.         cacheblock(blk, TRUE);
  238.  
  239.     switch(sectab[blk])
  240.     {
  241.         case SEC_NOT_LOADED:
  242.             curblk = blk;
  243.             cacheblock(blk, FALSE);
  244.             if(sectab[blk] == SEC_OK)
  245.                 return((struct DataBlock*)(diskimage+(blk*256)));
  246.             /* fall through */
  247.  
  248.         case SEC_ERROR:
  249.         default:
  250.         {
  251.             static struct EasyStruct req =
  252.             {
  253.                 sizeof(struct EasyStruct),
  254.                 0,
  255.                 "FS1541 Error",
  256.                 "Volume %s has a\nread/write error on\nblock %ld.",
  257.                 "Ignore|Ignore All|Abort All|Abort"
  258.             };
  259.  
  260.             if(curvolumenode)
  261.             {
  262.                 LONG num = -1;
  263.  
  264.                 if(abortall)
  265.                     num = 0;
  266.                 if(ignoreall)
  267.                     num = 1;
  268.  
  269.                 if(num == -1 && (IntuitionBase = (struct IntuitionBase*)OpenLibrary("intuition.library",36)))
  270.                 {
  271.                     struct Process *pr;
  272.  
  273.                     if((dpsender->mp_Flags & PF_ACTION) != PA_SIGNAL
  274.                     || (pr = dpsender->mp_SigTask)->pr_Task.tc_Node.ln_Type != NT_PROCESS
  275.                     || pr->pr_WindowPtr != (APTR)-1)
  276.                     {
  277.                         ULONG args[2] = { (ULONG)&curvolumenode->name[1], blk };
  278.  
  279.                         num = EasyRequestArgs(NULL, &req, NULL, &args);
  280.                     }
  281.                     else
  282.                         num = 0;
  283.  
  284.                     CloseLibrary((struct Library*)IntuitionBase);
  285.                 }
  286.  
  287.                 switch(num)
  288.                 {
  289.                     case 3: default:
  290.                         abortall = TRUE;
  291.                         /* fall through */
  292.                     case 0:
  293.                         return(NULL);
  294.  
  295.                     case 2:
  296.                         ignoreall = TRUE;
  297.                         /* fall through */                            
  298.                     case 1:
  299.                         return((struct DataBlock*)(diskimage+(blk*256)));
  300.                 }
  301.             }
  302.  
  303.             return(NULL);
  304.         }
  305.  
  306.         case SEC_OK:
  307.             return((struct DataBlock*)(diskimage+(blk*256)));
  308.     }
  309. }
  310.  
  311. static void cacheblock(ULONG n, BOOL write)
  312. {
  313.     diskreq->iotd_Count = chgcount;
  314.     diskreq->iotd_Req.io_Command = write ? ETD_WRITE : ETD_READ;
  315.     diskreq->iotd_Req.io_Flags = 0;
  316.     diskreq->iotd_Req.io_Data = diskimage+(n*256);
  317.     diskreq->iotd_Req.io_Offset = 256*n;
  318.     diskreq->iotd_Req.io_Length = 256;
  319.     if(!DoIO((struct IORequest*)diskreq))
  320.         sectab[n] = SEC_OK;
  321.     else
  322.     {
  323.         sectab[n] = SEC_ERROR;
  324.         numsofterrors++;
  325.  
  326.         if(!curvolumenode)
  327.         {
  328.             /* Switch off the motor, unread/writable disk. */
  329.             diskreq->iotd_Req.io_Command = TD_MOTOR;
  330.             diskreq->iotd_Req.io_Flags = 0;
  331.             diskreq->iotd_Req.io_Length = 0;
  332.             DoIO((struct IORequest*)diskreq);
  333.         }
  334.     }
  335. }
  336.